##############################
from chiori import Plugin, Ui, fcheck
import time
from libs.vk import get_ids, get_profiles
import math
import aiohttp
##############################

p = Plugin(name='vk: utils', sp=["vk"], backend='vk_cli', desc='инструменты для клиента вк')


# func
# ====

async def get_friends_friends(ctx, u, ids):
	user_ids = []
	users = []

	if not ids:
		res = await ctx.request('friends.get')

		if res["error"]:
			return []
		else:
			ids = res['response']['items']

	i = 0
	c = len(ids)
	for x in ids:

		i += 1
		res = await ctx.request('friends.get', user_id=x)


		for uid in res["response"]["items"]:
			if uid not in user_ids:
				user_ids.append(str(uid))

		u.progress_bar(i, c, "получение друзей друзей...")
		time.sleep(0.15)

	p.log(f'получено пользователей: {len(user_ids)}')
	if len(user_ids) < 1000:
		c = 1
	else:
		c = round(len(user_ids)/1000)

	for x in range(c):


		res = await ctx.request('users.get',
						user_ids=', '.join(user_ids[x*1000:x*1000+1000]),
						fields='blacklisted_by_me')

		for ud in res["response"]:
			if ud not in users:
				users.append(ud)

		u.progress_bar(x, c, 'получение пользователей...')
		time.sleep(0.15)

	return users


async def load_album(ctx, owner_id, data, path):
	u = Ui()
	errors = {}
	count = 0
	start_time = time.time()

	async with aiohttp.ClientSession() as session:
		for j in range(math.ceil(data['size'] / 1000)):

			fcheck(f'{path}/{j}', True)
			u.l.log(f'part {j} / {math.ceil(data["size"] / 1000)}', 'load')
			temp = await ctx.request('photos.get', owner_id=owner_id,
										album_id=data['id'], offset=j*1000,
										count=1000)

			for photo in temp['response']['items']:
				count += 1
				url = photo['sizes'][-1]['url']

				async with session.get(url) as r:
					if r.status == 200:
						with open(f"{path}/{j}/{count}.png", "wb") as f:
							f.write(await r.read())
						u.progress_bar(count, data['size'],
										suffix=time.time()-start_time,
										printEnd='\r')
					else:
						u.l.error(f'{url} - {r.status}')
						errors[count] = url

			print('')
			while errors:
				for k, v in list(errors.items()):
					status = await load_photo(v, f"{path}/{j}/{k}.png")
					if status:
						del errors[k]
					else:
						u.log(f'[{len(len(errors))}] {k}', 'reload')


async def load_albums(ctx, owner_id, album_ids=[]):
	if owner_id.isdigit():
		owner_id = int(owner_id)

	res = await ctx.request('photos.getAlbums', owner_id=owner_id, album_ids=', '.join(album_ids))
	if res["error"]:
		return False

	wall_albun = await ctx.request('photos.get', owner_id=owner_id, album_id='wall')
	albums = [{'id': 'wall', 'title': 'Стена.',
					'size':wall_albun['response']['count']}]

	for x in res['response']['items']:
		albums.append(x)

	album_pos = 0
	for x in albums:
		album_pos += 1

		p.log(f'[{x["id"]}] {x["title"]} -> {x["size"]}', f'{album_pos}/{len(albums)}')

		if input('load? [y/n] > ') == 'y':
			path = f'data/photo-parser/{owner_id}/{x["id"]}'
			fcheck('data/photo-parser', True)
			fcheck(f'data/photo-parser/{owner_id}', True)
			fcheck(path, True)

			await load_album(ctx, owner_id, x, path)


async def get_group_names(ctx, user_id=False, level=2):
	'''главная функция. Ничего сложного, разбивает названия на отдельные слова
	и подсчитывает их количество

	:param user_ud: требуемый id для получения списка групп.
	:param level: больше скольки раз должно повторяться слово для отображения'''

	# получаем список id групп
	u = Ui()
	temp = await ctx.request('groups.get', user_id=user_id)
	if temp['error']:
		return p.log('не удалось получить список групп', 'e')

	group_ids = ''
	for x in temp["response"]["items"]:
		group_ids += f'{x}, '

	# получаем имена групп
	groups = await ctx.request('groups.getById', group_ids=group_ids)
	if groups['error']:
		return u.l.log('не удалось получить список названий', 'e')

	names = []
	for x in groups['response']:
		names.append(x['name'].lower())

	raw_resuilt = {}
	for x in names:
		for word in x.split(' '):
			if len(word) > 2:
				if word	not in raw_resuilt:
					raw_resuilt[word] = 1
				else:
					raw_resuilt[word] += 1

	# очистка + поиск
	max_count = max(raw_resuilt.values())
	resuilt = {}
	other_words = []
	for k, v in list(raw_resuilt.items()):
		if v > level:
			resuilt[k] = v
		else:
			other_words.append(k)

	p.log(f'групп пользователя: {len(groups["response"])}')
	for k, v in sorted(resuilt.items(),  key=lambda x: x[1], reverse=True):
		u.progress_bar(v, max_count, suffix=k)
	p.log(f'уникальных слов: {len(other_words)}')


def print_names(u, pr):
	text = ''
	for k, v in pr.items():
		print(v)
		text += f'\n- {u.blue}{k}{u.gray}: {u.yellow}{v["name"]}{u.reset}'
	return text


# commands
# ========

@p.command('blocked', 'b', usage='заблокировавшие вас пользователи')
async def getBlocked(event, ctx):
	u = Ui()

	p.log('получение друзей друзей...')
	ids = await get_ids(event, ctx)

	users = await get_friends_friends(ctx, u, ids)
	blocked = []

	for ud in users:
		if ud.get("blacklisted_by_me"):
			p.log(ud)
			blocked.append(ud)

	p.log(str(blocked), 'blocked')

	pr = await get_profiles(event, ctx, blocked or [])

	text = f'заблокировавшие вас пользователи: {len(pr)}'
	text += print_names(u, pr)

	u.form(text)


@p.command('id', 'ids', usage='получить пользователей по их id')
async def getUserId(event, ctx):
	u = Ui()
	pr = await get_profiles(event, ctx, await get_ids(event, ctx))
	u.form(f'id пользователей: {print_names(u, pr)}')


@p.command('<l(oad) p(hoto)/a(lbum)>', 'load', 'la')
async def loadAlbum(event, ctx):
	if 'vk.com' in ctx.sargs:
		params = ctx.sargs.split('/')[-1].strip('album').split('_')
		print(params)
		await load_albums(ctx, params[0], params[1:])

	elif ctx.sargs:
		print(ctx.sargs)
		await load_albuns(ctx, ctx.sargs)


@p.command('groups', 'g')
async def userGroups(event, ctx):
	uid, args = await get_id(event, ctx)
	await get_group_names(ctx, uid)


@p.command('<u(ser) s(earch)>')
async def searchUserFromIds(event, ctx):

	u = Ui()
	users = []
	ids = await get_ids(event, ctx)

	for x in ids:
		res = await ctx.request('friends.get', user_id=x)
		if res['error']:
			continue

		if not users:
			users = res['response']['items']
		else:
			users = list(set(users) & set(res["response"]['items']))

	users = list(map(lambda x: str(x), users))
	pr = await get_profiles(event, ctx, users)
	u.form(print_names(u, pr))

